﻿namespace Cellfish.Toolbox.Linq
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Provides extension methods to 'tap' into an source meaning
    /// when the source is enumerated the tap gets to inspect each item.
    /// </summary>
    public static class TapExtension
    {
        /// <summary>
        /// Taps the specified enumerable.
        /// </summary>
        /// <typeparam name="T">Type of items in enumerable.</typeparam>
        /// <param name="source">The source enumerable.</param>
        /// <param name="tapAction">The tap action.</param>
        /// <returns>An enumerable containing all elements in the source.</returns>
        /// <exception cref="System.ArgumentNullException">If source is null.</exception>
        /// <exception cref="System.ArgumentNullException">If tapAction is null.</exception>
        public static IEnumerable<T> Tap<T>(this IEnumerable<T> source, Action<T> tapAction)
        {
            if (tapAction == null)
            {
                throw new ArgumentNullException("tapAction");
            }

            return source.Select(
                item =>
                    {
                        tapAction(item);
                        return item;
                    });
        }

        /// <summary>
        /// Taps the specified enumerable providing an index to the tapAction.
        /// </summary>
        /// <typeparam name="T">Type of items in enumerable.</typeparam>
        /// <param name="source">The source enumerable.</param>
        /// <param name="tapAction">The tap action with index parameter.</param>
        /// <returns>An enumerable containing all elements in the source.</returns>
        /// <exception cref="System.ArgumentNullException">If source is null.</exception>
        /// <exception cref="System.ArgumentNullException">If tapAction is null.</exception>
        public static IEnumerable<T> Tap<T>(this IEnumerable<T> source, Action<T, int> tapAction)
        {
            int index = 0;
            return source.Tap(item => tapAction(item, index++));
        }
    }
}
